package cn.maihe.elg.operation.service.order;

import cn.maihe.elg.operation.centers.epoint.dto.handler.MeiShanProjectInfoDecryptionVo;
import cn.maihe.elg.operation.centers.follow.channel.dto.GuarantorStatusNoticeReqDTO;
import cn.maihe.elg.operation.centers.guogu.dto.channel.req.GuoGuReductionNotifyReq;
import cn.maihe.elg.operation.centers.supports.CenterInterfaceService;
import cn.maihe.elg.operation.centers.supports.CenterInterfaceServiceFactory;
import cn.maihe.elg.operation.centers.supports.model.bo.InnerUploadBaohanFileBo;
import cn.maihe.elg.operation.centers.supports.model.bo.NoticePayResultBo;
import cn.maihe.elg.operation.centers.supports.model.bo.PushCenterGuaranteeBo;
import cn.maihe.elg.operation.config.ZtAccountInfo;
import cn.maihe.elg.operation.exception.ErrorCode;
import cn.maihe.elg.operation.exception.SystemRuntimeException;
import cn.maihe.elg.operation.model.bo.GuaranteeTemplatePdfParams;
import cn.maihe.elg.operation.model.bo.ReceiveTemplatePdfParams;
import cn.maihe.elg.operation.model.dto.InnerBaseResp;
import cn.maihe.elg.operation.model.dto.institution.PushGuaranteeRespDTO;
import cn.maihe.elg.operation.model.enums.AcceptOrderStatus;
import cn.maihe.elg.operation.model.enums.ApplyOrderStatus;
import cn.maihe.elg.operation.model.enums.AttachmentFileType;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.model.enums.GuaranteeStatus;
import cn.maihe.elg.operation.model.enums.GuaranteeTemplateType;
import cn.maihe.elg.operation.model.enums.InnerRespCode;
import cn.maihe.elg.operation.model.enums.InvoiceFlagEnum;
import cn.maihe.elg.operation.model.enums.InvoiceStatusEnum;
import cn.maihe.elg.operation.model.enums.NoticeTypeEnum;
import cn.maihe.elg.operation.model.enums.SignatureFileTypeEnum;
import cn.maihe.elg.operation.model.vo.order.ApplyOrderDetailVO;
import cn.maihe.elg.operation.model.vo.order.ApplyOrderStatusOperateVO;
import cn.maihe.elg.operation.model.vo.order.ListApplyOrderDO;
import cn.maihe.elg.operation.model.vo.order.ListApplyOrderVO;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.ApplyOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.ApplyOrderInfoDOCondition;
import cn.maihe.elg.operation.repository.entity.BidCustomerDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeAttachmentInfoDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeInstitutionDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeProgressInfoDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeVo;
import cn.maihe.elg.operation.repository.entity.InvoiceInfoDO;
import cn.maihe.elg.operation.repository.entity.OrganizationDO;
import cn.maihe.elg.operation.repository.entity.ProjectInfoDO;
import cn.maihe.elg.operation.repository.entity.SellerInfoDO;
import cn.maihe.elg.operation.repository.entity.SellerInfoDOCondition;
import cn.maihe.elg.operation.service.BaseDaoService;
import cn.maihe.elg.operation.service.business.BidCustomerService;
import cn.maihe.elg.operation.service.business.CustomerAttachmentService;
import cn.maihe.elg.operation.service.business.ExchangeCenterService;
import cn.maihe.elg.operation.service.business.InstitutionService;
import cn.maihe.elg.operation.service.business.ProjectInfoService;
import cn.maihe.elg.operation.service.guarantee.GuaranteeService;
import cn.maihe.elg.operation.service.invoice.InvoiceInfoService;
import cn.maihe.elg.operation.service.invoice.SellerInfoService;
import cn.maihe.elg.operation.service.system.OrganizationService;
import cn.maihe.elg.operation.supports.bank.cmb.util.CashServiceUtil;
import cn.maihe.elg.operation.supports.electronicseal.jd.JDSignatureSupport;
import cn.maihe.elg.operation.supports.electronicseal.jd.dto.req.SignatureAttachment;
import cn.maihe.elg.operation.supports.electronicseal.kt.cloudsign.KTOfdCloudSignService;
import cn.maihe.elg.operation.supports.electronicseal.ms.MSOFDSignSupport;
import cn.maihe.elg.operation.supports.invoice.nuonuo.InvoiceHelper;
import cn.maihe.elg.operation.supports.system.ElgResourceService;
import cn.maihe.elg.operation.utils.CreateGuaranteeUtil;
import cn.maihe.elg.operation.utils.CurrencyUpperUtil;
import cn.maihe.elg.operation.utils.DateUtil;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.elg.operation.utils.IdGenerate;
import cn.maihe.elg.operation.utils.OfdStructXmlUtil;
import cn.maihe.elg.operation.utils.StringUtil;
import cn.maihe.elg.operation.utils.UserContextUtil;
import cn.maihe.framework.starter.base.sql.PageBo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.kinsec.dom.Attachment;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
 * @Description 向出函机构申请开立保函订单
 * @Author WJH
 * @Date 2021/03/25
 */
@Service
@Slf4j
public class ApplyOrderInfoService extends BaseDaoService<ApplyOrderInfoDO> {

    @Resource
    private GuaranteeAttachmentInfoService guaranteeAttachmentInfoService;
    @Resource
    private GuaranteeProgressInfoService guaranteeProgressInfoService;
    @Resource
    private ProjectInfoService projectInfoService;
    @Resource
    private InstitutionService institutionService;
    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    private ElgResourceService elgResourceService;
    @Resource
    private ExchangeCenterService exchangeCenterService;
    @Resource
    private GuaranteeService guaranteeService;
    @Resource
    private BidCustomerService bidCustomerService;
    @Resource
    private OrganizationService organizationService;
    @Resource
    private CustomerAttachmentService customerAttachmentService;

    @Resource
    private SellerInfoService sellerInfoService;
    @Resource
    private InvoiceInfoService invoiceInfoService;
    @Resource
    private InvoiceHelper invoiceHelper;
    @Resource
    private NoticeRetryInfoService noticeRetryInfoService;
    @Resource
    private ZtAccountInfo ztAccountInfo;
    @Resource
    private KTOfdCloudSignService ktOfdCloudSignService;

    @Resource
    private JDSignatureSupport jdSignatureSupport;

    @Resource
    private MSOFDSignSupport msofdSignSupport;

    @Resource(name = "resultNoticeHandleExecutor")
    private ThreadPoolTaskExecutor executor;


    public PageBo<ListApplyOrderDO> selectPageBySql(int pageNo, int pageSize, ListApplyOrderVO vo) {
        Map<String, Object> paramsMap = toMapAndAddParams(vo);
        //订单时间
        if (vo.getGmtCreateRange() != null && vo.getGmtCreateRange().length == 2) {
            String[] rangeAy = vo.getGmtCreateRange();
            if (StringUtils.isNoneBlank(rangeAy[0], rangeAy[1])) {
                paramsMap.put("startGmtCreate", DateUtil.parseDate(rangeAy[0] + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
                paramsMap.put("endGmtCreate", DateUtil.parseDate(rangeAy[1] + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
            }
        }
        return this.selectPageBySql("selectApplyOrderList", "selectApplyOrderCount", paramsMap, pageNo, pageSize);
    }


    public Integer updateByAcceptOrderNo(ApplyOrderInfoDO updateDO, String acceptOrderNo) {
        ApplyOrderInfoDOCondition condition = ApplyOrderInfoDOCondition.builder().andAcceptOrderNoEq(acceptOrderNo);
        return this.update(updateDO, condition.build());
    }

    public ApplyOrderInfoDO getByGuaranteeNo(String guaranteeNo) {
        ApplyOrderInfoDOCondition condition = ApplyOrderInfoDOCondition.builder().andGuaranteeNoEq(guaranteeNo);
        return this.selectOne(condition.build());
    }

    public ApplyOrderInfoDO getByAcceptOrderNo(String acceptOrderNo) {
        ApplyOrderInfoDOCondition condition = ApplyOrderInfoDOCondition.builder().andAcceptOrderNoEq(acceptOrderNo);
        return this.selectOne(condition.build());
    }

    public ApplyOrderInfoDO getByCenterOrderId(String centerOrderId) {
        ApplyOrderInfoDOCondition condition = ApplyOrderInfoDOCondition.builder().andCenterOrderIdEq(centerOrderId);
        return this.selectOne(condition.build());
    }

    /**
     * 随行光泽平台，直接在申请订单服务类完成，不再通过出函机构处理后返回
     *
     * @param vo
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
    public void applyGuarantee(AcceptOrderInfoDO vo, InvoiceInfoDO invoiceInfoDO, GuaranteeDO correctGuaranteeDO, boolean restoreFlag) {
        CenterNoEnum centerNoEnum = exchangeCenterService.getCenterNoEnumById(vo.getCenterId());
        GuaranteeTemplateType guaranteeTemplateType = GuaranteeTemplateType.resolve(vo.getTemplateId());
        Assert.notNull(guaranteeTemplateType, "保函模板id为空");

        ProjectInfoDO projectInfoDO = projectInfoService.selectById(vo.getProjectId());
        Date bidIndate = projectInfoDO.getBidIndate();
        Date guaranteeTime = Date.from(Instant.now());
        if(!restoreFlag && Objects.nonNull(bidIndate)){
             if(!guaranteeTime.before(bidIndate)){
                 throw new RuntimeException("已经过了投标截止时间，不允许出函");
             }
        }

        GuaranteeInstitutionDO guaranteeInstitutionDO = institutionService.selectById(vo.getInstitutionId());
        //1 生成 申请保函订单记录
        ApplyOrderInfoDO applyOrderInfoDO = ApplyOrderInfoDO.builder().id(IdGenerate.getId())
                .orgId(vo.getOrgId()).centerId(vo.getCenterId())
                .guaranteeNo(vo.getGuaranteeNo()).guaranteeTime(guaranteeTime)
                .centerOrderId(vo.getCenterOrderId()).acceptOrderNo(vo.getAcceptOrderNo()).applyOrderNo(vo.getApplyOrderNo())
                .guaranteeType(vo.getGuaranteeType()).guaranteeCategory(vo.getGuaranteeCategory())
                .guaranteeFee(vo.getGuaranteeFee())
                .projectId(vo.getProjectId()).projectName(vo.getProjectName()).sectionName(vo.getSectionName())
                .bidCustomerId(vo.getBidCustomerId()).bidCustomerName(vo.getBidCustomerName())
                .bidIndate(vo.getBidIndate()).bidBond(projectInfoDO.getBidBond())
                .institutionId(vo.getInstitutionId()).institutionName(guaranteeInstitutionDO.getGuarantorName())
                .attachmentId(vo.getAttachmentId())
                //初始化 待出函
                .status(ApplyOrderStatus.WAIT_OUT_GUARANTEE.getStatus())
                .gmtCreate(Date.from(Instant.now())).gmtModified(Date.from(Instant.now()))
                .userCreate(UserContextUtil.getCurUserName() != null ? UserContextUtil.getCurUserName() : "system")
                .userModified(UserContextUtil.getCurUserName() != null ? UserContextUtil.getCurUserName() : "system")
                .remark("生成向出函机构申请电子保函记录").inviteCode(vo.getInviteCode())
                .build();

        this.insert(applyOrderInfoDO);

        if (CreateGuaranteeUtil.isIssueInvoice(centerNoEnum,vo.getClientId())) {
            //2. 查询发票
            if (invoiceInfoDO == null || StringUtils.isBlank(invoiceInfoDO.getInvoiceNo())
                    || invoiceInfoDO.getStatus() == null
                    || InvoiceStatusEnum.INVOICED.getValue() != invoiceInfoDO.getStatus()) {
                throw new RuntimeException("保函未开电子发票，请开票后再试");
            }
        }

        //3.电子保函保单签章
        Path guaranteePdf = genGuaranteePdfAndSealedOfd(SignatureFileTypeEnum.PDF,vo, guaranteeTemplateType, applyOrderInfoDO, correctGuaranteeDO, null, centerNoEnum, restoreFlag, guaranteeInstitutionDO,null);

        //4.到账证明签章
        Path receiveOfd = genReceivePdfAndOfd(applyOrderInfoDO, centerNoEnum);

        //5.资质文件
        Path qualificationPath = customerAttachmentService.getBidQualificationFile(applyOrderInfoDO.getBidCustomerId(), centerNoEnum,vo.getClientId());
        // 6.营业执照
        Path licensePath = customerAttachmentService.getBidBusinessLicFile(applyOrderInfoDO.getBidCustomerId(), centerNoEnum,vo.getClientId());

        // 7.申请书 & 反担保承诺书 目前是统一文件 客户自行签章后上送
        Path applyFilePdf = guaranteeAttachmentInfoService.getGuaAttPath(applyOrderInfoDO.getAcceptOrderNo(), AttachmentFileType.TYPE_11);
        Path applyFileEdc = guaranteeAttachmentInfoService.getGuaAttPathNoAuth(applyOrderInfoDO.getAcceptOrderNo(), AttachmentFileType.TYPE_15);
        if (applyFileEdc == null) {
            applyFileEdc = applyFilePdf;
        }

        BidCustomerDO bidCustomerDO = bidCustomerService.selectById(applyOrderInfoDO.getBidCustomerId());
        int validPeriod = projectInfoDO.getValidPeriod() == null ? 0 : projectInfoDO.getValidPeriod();
        OrganizationDO organizationDO = organizationService.getOrganization(applyOrderInfoDO.getOrgId());
        // 8. 保存保函信息表中保函文件及md5取值 包含附件的ofd文件
        if (CreateGuaranteeUtil.isSetBidOpenTime(restoreFlag,centerNoEnum,vo.getClientId(), projectInfoDO.getProjectEncryptionFlag())) {
            projectInfoDO.setBidOpenTime(DateUtil.parseDate(DateUtil.getDatetime(), DateUtil.FORMAT_DATETIME));
        }
        Date serviceEndTime = Date.from(projectInfoDO.getBidOpenTime().toInstant()
                .plus(validPeriod + 28, ChronoUnit.DAYS));
        if (correctGuaranteeDO != null && correctGuaranteeDO.getServiceEndTime() != null) {
            serviceEndTime = correctGuaranteeDO.getServiceEndTime();
        }
        GuaranteeDO guaranteeDO = GuaranteeDO.builder().id(IdGenerate.getId())
                .centerId(applyOrderInfoDO.getCenterId()).orgId(applyOrderInfoDO.getOrgId())
                .guaranteeNo(applyOrderInfoDO.getGuaranteeNo())
                .institutionId(applyOrderInfoDO.getInstitutionId()).centerOrderId(applyOrderInfoDO.getCenterOrderId())
                .acceptOrderNo(applyOrderInfoDO.getAcceptOrderNo()).applyOrderNo(applyOrderInfoDO.getApplyOrderNo())
                .serviceBeginTime(projectInfoDO.getBidOpenTime()).serviceEndTime(serviceEndTime).bidBond(projectInfoDO.getBidBond())
                .amount(applyOrderInfoDO.getGuaranteeFee()).guaranteeType(applyOrderInfoDO.getGuaranteeType())
                .guaranteeCategory(applyOrderInfoDO.getGuaranteeCategory()).projectCode(projectInfoDO.getProjectCode())
                .projectName(projectInfoDO.getProjectName()).sectionCode(projectInfoDO.getSectionCode()).sectionName(projectInfoDO.getSectionName())
                .bidCustomerName(applyOrderInfoDO.getBidCustomerName()).guarantorName(applyOrderInfoDO.getInstitutionName()).tenderer(projectInfoDO.getTenderer())
                .guaranteeTime(applyOrderInfoDO.getGuaranteeTime()).remark("开函完成").gmtModified(Date.from(Instant.now()))
                .guaranteeStatus(GuaranteeStatus.PROTECTING.getStatus())
                .build();

        if(!CreateGuaranteeUtil.isGuoGu(centerNoEnum) && !CreateGuaranteeUtil.isMeiShan(centerNoEnum)){
            guaranteeDO.setGuaranteeCheckNo(StringUtil.genGuaranteeCheckNo());
        }

        PushGuaranteeRespDTO respDTO = new PushGuaranteeRespDTO();
        respDTO.setApplyOrderId(applyOrderInfoDO.getId());
        respDTO.setAcceptOrderNo(applyOrderInfoDO.getAcceptOrderNo());
        respDTO.setGuaranteeNo(applyOrderInfoDO.getGuaranteeNo());
        respDTO.setGuaranteeTime(applyOrderInfoDO.getGuaranteeTime());

        respDTO.setGuaranteeFile(guaranteePdf);
        respDTO.setReceiveAmtFile(receiveOfd);
        respDTO.setApplyFile(applyFilePdf);
        respDTO.setQualificationPath(qualificationPath);
        respDTO.setLicensePath(licensePath);

        if (CreateGuaranteeUtil.isSynthesisGuaranteeAllOfd(centerNoEnum,vo.getClientId())) {
            // 9.xml保存文件路径
            Path targetXmlPath = elgResourceService.buildSaveAbsolutePath("ofd", applyOrderInfoDO.getAcceptOrderNo(), "结构化数据文件", "xml");
            Path ofdStructXmlPath = OfdStructXmlUtil.genOfdStructXml(elgResourceService, targetXmlPath,
                    applyOrderInfoDO, organizationDO, projectInfoDO, bidCustomerDO, guaranteeDO, invoiceInfoDO,
                    guaranteePdf, receiveOfd, qualificationPath, licensePath, applyFilePdf, applyFileEdc, centerNoEnum,vo.getClientId());
            respDTO.setOfdStructXmlPath(ofdStructXmlPath);

            // 10 添加电子保函附件
            ArrayList<Attachment> attachments = null;
            ArrayList<SignatureAttachment> signatureAttachments = null;
            if(CreateGuaranteeUtil.isXiaMen(centerNoEnum)){
                signatureAttachments = signatureAttachment(guaranteePdf, receiveOfd, qualificationPath, licensePath, applyFilePdf, applyFileEdc, ofdStructXmlPath);
            } else {
                attachments = buildAttachments(guaranteePdf, receiveOfd, qualificationPath, licensePath, applyFilePdf, applyFileEdc, ofdStructXmlPath);
            }
            // 11.整体添加附件后再进行电子保函签章
            Path guaranteeAllOfd = genGuaranteePdfAndSealedOfd(SignatureFileTypeEnum.OFD,vo,guaranteeTemplateType, applyOrderInfoDO, correctGuaranteeDO, attachments, centerNoEnum, restoreFlag, guaranteeInstitutionDO,signatureAttachments);
            respDTO.setAllFileOfdPath(guaranteeAllOfd);
        }

        respDTO.setGuaranteeDO(guaranteeDO);
        // 12. 开函结果回调中心
        receivePushGuaranteeSuccess(respDTO, restoreFlag);

        //统计相同客户&投标相同项目数
        acceptOrderInfoService.updateGuaranteeCount(vo.getBidCustomerId(), vo.getProjectId());

    }


    private ArrayList<Attachment> buildAttachments(Path guaranteePdf, Path receiveOfd, Path qualificationPath, Path licensePath, Path applyFile, Path applyFileEdc, Path ofdStructXmlPath) {
        try {
            Attachment guaranteeOfdAtt = new Attachment("电子保单（合同）原文件", elgResourceService.getFileType(guaranteePdf), Files.newInputStream(guaranteePdf));
            Attachment guaranteeOfdAttPdf = new Attachment("电子保单（合同）PDF文件", elgResourceService.getFileType(guaranteePdf), Files.newInputStream(guaranteePdf));
            Attachment applyFileAtt = new Attachment("电子保函申请单原文件", elgResourceService.getFileType(applyFileEdc), Files.newInputStream(applyFileEdc));
            Attachment applyFileAttPdf = new Attachment("电子保函申请单PDF文件", elgResourceService.getFileType(applyFile), Files.newInputStream(applyFile));

            Attachment qualificationAtt = new Attachment("企业资质文件", elgResourceService.getFileType(qualificationPath), Files.newInputStream(qualificationPath));
            Attachment licenseAtt = new Attachment("企业营业执照", elgResourceService.getFileType(licensePath), Files.newInputStream(licensePath));
            Attachment receiveOfdAtt = new Attachment("到账证明", elgResourceService.getFileType(receiveOfd), Files.newInputStream(receiveOfd));
            Attachment ofdStructXmlAtt = new Attachment("结构化数据文件", "xml", Files.newInputStream(ofdStructXmlPath));
            return Lists.newArrayList(guaranteeOfdAtt, guaranteeOfdAttPdf, applyFileAtt, applyFileAttPdf,
                    qualificationAtt, licenseAtt, receiveOfdAtt, ofdStructXmlAtt);
        } catch (IOException e) {
            throw new RuntimeException("添加附件失败:" + e.getMessage(), e);
        }

    }

    private ArrayList<SignatureAttachment> signatureAttachment(Path guaranteePdf, Path receiveOfd, Path qualificationPath, Path licensePath, Path applyFile, Path applyFileEdc, Path ofdStructXmlPath) {
            SignatureAttachment guaranteeOfdAtt = new SignatureAttachment("电子保单（合同）原文件", elgResourceService.getFileType(guaranteePdf), guaranteePdf);
            SignatureAttachment guaranteeOfdAttPdf = new SignatureAttachment("电子保单（合同）PDF文件", elgResourceService.getFileType(guaranteePdf), guaranteePdf);
            SignatureAttachment applyFileAtt = new SignatureAttachment("电子保函申请单原文件", elgResourceService.getFileType(applyFileEdc), applyFileEdc);
            SignatureAttachment applyFileAttPdf = new SignatureAttachment("电子保函申请单PDF文件", elgResourceService.getFileType(applyFile), applyFile);
            SignatureAttachment qualificationAtt = new SignatureAttachment("企业资质文件", elgResourceService.getFileType(qualificationPath), qualificationPath);
            SignatureAttachment licenseAtt = new SignatureAttachment("企业营业执照", elgResourceService.getFileType(licensePath), licensePath);
            SignatureAttachment receiveOfdAtt = new SignatureAttachment("到账证明", elgResourceService.getFileType(receiveOfd), receiveOfd);
            SignatureAttachment ofdStructXmlAtt = new SignatureAttachment("结构化数据文件", "xml",ofdStructXmlPath);
            return Lists.newArrayList(guaranteeOfdAtt, guaranteeOfdAttPdf, applyFileAtt, applyFileAttPdf,
                    qualificationAtt, licenseAtt, receiveOfdAtt, ofdStructXmlAtt);
    }
    /**
     * 到账证明签章
     */
    private Path genReceivePdfAndOfd(ApplyOrderInfoDO applyOrderInfoDO, CenterNoEnum centerNoEnum) {
        ProjectInfoDO projectInfoDO = projectInfoService.selectById(applyOrderInfoDO.getProjectId());
        BidCustomerDO bidCustomerDO = bidCustomerService.selectById(applyOrderInfoDO.getBidCustomerId());
        OrganizationDO organizationDO = organizationService.getOrganization(applyOrderInfoDO.getOrgId());
        AcceptOrderInfoDO acceptOrderInfo = acceptOrderInfoService.getByAcceptOrderNo(applyOrderInfoDO.getAcceptOrderNo());

        ReceiveTemplatePdfParams pdfParams = new ReceiveTemplatePdfParams();

        pdfParams.setProjectCode(projectInfoDO.getProjectCode());
        pdfParams.setPayeeAccNo(ztAccountInfo.getAccNo());
        pdfParams.setPayerAccNo(bidCustomerDO.getBankCardNum());
        Triple<String, String, String> triple = DateUtil.parseLocalDate();
        pdfParams.setSignYear(triple.getLeft());
        pdfParams.setSignMonth(triple.getMiddle());
        pdfParams.setSignDay(triple.getRight());

        pdfParams.setGuaranteeNo(applyOrderInfoDO.getGuaranteeNo());
        pdfParams.setTenderName(projectInfoDO.getTenderer());
        pdfParams.setBidderName(applyOrderInfoDO.getBidCustomerName());
        pdfParams.setProjectName(applyOrderInfoDO.getProjectName());
        pdfParams.setSectionName(applyOrderInfoDO.getSectionName());
        pdfParams.setGuaranteeFee(StringUtil.fen2YuanCurrency(applyOrderInfoDO.getBidBond()));
        //签署日期取 出函时间
        Triple<String, String, String> openDate = DateUtil.parseLocalDate(applyOrderInfoDO.getGuaranteeTime());
        pdfParams.setYear(openDate.getLeft());
        pdfParams.setMonth(openDate.getMiddle());
        pdfParams.setDay(openDate.getRight());
        pdfParams.setInstitutionName(organizationDO.getFullName());

        //到账时间取值页面录入时间
        String[] receiveDate = acceptOrderInfo.getPayTime().split("-");
        pdfParams.setPayYear(receiveDate[0]);
        pdfParams.setPayMonth(receiveDate[1]);
        pdfParams.setPayDay(receiveDate[2]);

        if (!CreateGuaranteeUtil.isGuoGu(centerNoEnum) && !CreateGuaranteeUtil.isMeiShan(centerNoEnum)) {
            if (StringUtils.isBlank(pdfParams.getProjectCode())) {
                throw new RuntimeException("参数校验异常：" + "项目编号不能为空");
            }

            if (StringUtils.isBlank(pdfParams.getProjectName())) {
                throw new RuntimeException("参数校验异常：" + "项目名称不能为空");
            }

            if (StringUtils.isBlank(pdfParams.getSectionName())) {
                throw new RuntimeException("参数校验异常：" + "标段名称不能为空");
            }
        }
//        return ktPdfCloudSignService.receivePdfSeal(applyOrderInfoDO.getAcceptOrderNo(), pdfParams);
        return ktOfdCloudSignService.receivePdfSeal(applyOrderInfoDO.getAcceptOrderNo(), pdfParams);
//        return ktOFDService.receiveOfdSeal(applyOrderInfoDO.getAcceptOrderNo(), pdfParams);
    }

    /**
     * 保函模板合成pdf并凯特签章转ofd
     */
    private Path genGuaranteePdfAndSealedOfd(SignatureFileTypeEnum signatureFileTypeEnum,AcceptOrderInfoDO acceptOrderInfoDO,GuaranteeTemplateType guaranteeTemplateType, ApplyOrderInfoDO applyOrderInfoDO,
                                             GuaranteeDO correctGuaranteeDO, ArrayList<Attachment> attachments,
                                             CenterNoEnum centerNoEnum, boolean restoreFlag,GuaranteeInstitutionDO guaranteeInstitutionDO,
                                             ArrayList<SignatureAttachment> signatureAttachments) {
        ProjectInfoDO projectInfoDO = projectInfoService.selectById(applyOrderInfoDO.getProjectId());
        BidCustomerDO bidCustomerDO = bidCustomerService.selectById(applyOrderInfoDO.getBidCustomerId());

        GuaranteeTemplatePdfParams pdfParams = assemblePdfParams(acceptOrderInfoDO, applyOrderInfoDO, correctGuaranteeDO,  centerNoEnum, guaranteeTemplateType,  restoreFlag, projectInfoDO, bidCustomerDO,false, guaranteeInstitutionDO,applyOrderInfoDO.getGuaranteeTime());
        if(CreateGuaranteeUtil.isXiaMen(centerNoEnum)){
            return jdSignatureSupport.getSignatureFile(signatureFileTypeEnum,
                    guaranteeInstitutionDO,
                    centerNoEnum,
                    acceptOrderInfoDO,
                    projectInfoDO,
                    bidCustomerDO,
                    pdfParams,
                    signatureAttachments);
        }

        GuaranteeTemplatePdfParams pdfParamsForCiphertext = assemblePdfParamsForCiphertext(acceptOrderInfoDO, applyOrderInfoDO, correctGuaranteeDO,  centerNoEnum, guaranteeTemplateType,  restoreFlag, projectInfoDO, bidCustomerDO, guaranteeInstitutionDO);

        Path guaranteeFile;
        if (CollectionUtils.isEmpty(attachments)) {
            // 单个文件pdf签章
            guaranteeFile = ktOfdCloudSignService.guaranteePdfSeal(applyOrderInfoDO.getAcceptOrderNo(), pdfParams, pdfParamsForCiphertext, centerNoEnum);
        } else {
            if(CreateGuaranteeUtil.isMeiShan(centerNoEnum)){
                guaranteeFile =  msofdSignSupport.getSignatureFile(
                        acceptOrderInfoDO,
                        projectInfoDO,
                        pdfParams,
                        restoreFlag);
            } else {
                if(CreateGuaranteeUtil.isMeiShan(centerNoEnum)){
                    attachments = null;
                }
                Map<String, String> metas = assembleMetas(applyOrderInfoDO,projectInfoDO,bidCustomerDO);
                // ofd签章
                guaranteeFile = ktOfdCloudSignService.guaranteeOfdWithAttachesSeal(applyOrderInfoDO.getAcceptOrderNo(), applyOrderInfoDO.getCenterOrderId(), pdfParams, pdfParamsForCiphertext, attachments, applyOrderInfoDO.getOrgId(), metas, centerNoEnum);

            }
        }
        return guaranteeFile;
    }

    private Map<String, String> assembleMetas(ApplyOrderInfoDO applyOrderInfoDO,ProjectInfoDO projectInfoDO,BidCustomerDO bidCustomerDO){
        GuaranteeInstitutionDO guaranteeInstitutionDO = institutionService.getInstitutionByAcceptOrderNo(applyOrderInfoDO.getAcceptOrderNo());
        Map<String, String> metas = new HashMap<>();
        metas.put("电子投标保函编号", applyOrderInfoDO.getGuaranteeNo());
        metas.put("担保额度", CurrencyUpperUtil.fenToYuanNum(applyOrderInfoDO.getBidBond()));
        metas.put("保费", CurrencyUpperUtil.fenToYuan(applyOrderInfoDO.getGuaranteeFee()));
        metas.put("招标项目编号", projectInfoDO.getProjectCode());
        metas.put("招标项目名称", projectInfoDO.getProjectName());
        metas.put("标段编号", projectInfoDO.getSectionCode());
        metas.put("标段名称", projectInfoDO.getSectionName());
        metas.put("投标人名称", bidCustomerDO.getBidderName());
        metas.put("投标人统一社会信用代码", bidCustomerDO.getBidderCreditCode());
        metas.put("招标人名称", projectInfoDO.getTenderer());
        metas.put("招标人统一社会信用代码", projectInfoDO.getTendererCreditCode());
        metas.put("工程担保保证人名称", guaranteeInstitutionDO.getGuarantorName());
        metas.put("工程担保保证人统一社会信用代码", guaranteeInstitutionDO.getGuarantorCreditCode());
        return metas;
    }

    private GuaranteeTemplatePdfParams assemblePdfParamsForCiphertext(AcceptOrderInfoDO vo,ApplyOrderInfoDO applyOrderInfoDO,GuaranteeDO correctGuaranteeDO,
                                                                      CenterNoEnum centerNoEnum,GuaranteeTemplateType guaranteeTemplateType,
                                                                      boolean restoreFlag,ProjectInfoDO projectInfoDO,BidCustomerDO bidCustomerDO,GuaranteeInstitutionDO guaranteeInstitutionDO) {
       log.info("assemblePdfParamsForCiphertext projectInfoDO.getProjectEncryptionFlag():{}",projectInfoDO.getProjectEncryptionFlag());
        if(CreateGuaranteeUtil.isMeiShan(centerNoEnum) && projectInfoDO.getProjectEncryptionFlag()==2){
            JSONObject ciphertext = JSON.parseObject(projectInfoDO.getCiphertext());
            MeiShanProjectInfoDecryptionVo meiShanProjectInfoDecryptionVo = JSON.parseObject(ciphertext.getString("meiShanProjectInfoDecryptionVo"), MeiShanProjectInfoDecryptionVo.class);
            log.info("assemblePdfParamsForCiphertext projectInfoDO:{}",JSON.toJSONString(projectInfoDO));
            log.info("assemblePdfParamsForCiphertext meiShanProjectInfoDecryptionVo:{}",JSON.toJSONString(meiShanProjectInfoDecryptionVo));
            ProjectInfoDO projectInfoDecryptionDO = new ProjectInfoDO();
            BeanUtils.copyProperties(projectInfoDO,projectInfoDecryptionDO);
            BeanUtils.copyProperties(meiShanProjectInfoDecryptionVo,projectInfoDecryptionDO);
            log.info("assemblePdfParamsForCiphertext projectInfoDecryptionDO:{}",JSON.toJSONString(projectInfoDecryptionDO));
            GuaranteeTemplatePdfParams guaranteeTemplatePdfParams = assemblePdfParams(vo, applyOrderInfoDO, correctGuaranteeDO, centerNoEnum, guaranteeTemplateType, restoreFlag, projectInfoDecryptionDO, bidCustomerDO,true, guaranteeInstitutionDO,vo.getGuaranteeTime());
            log.info("assemblePdfParamsForCiphertext guaranteeTemplatePdfParams:{}",JSON.toJSONString(guaranteeTemplatePdfParams));
            return guaranteeTemplatePdfParams;
        }else {
            return null;
        }
    }




    private GuaranteeTemplatePdfParams assemblePdfParams(AcceptOrderInfoDO vo,ApplyOrderInfoDO applyOrderInfoDO,GuaranteeDO correctGuaranteeDO,
                                                         CenterNoEnum centerNoEnum,GuaranteeTemplateType guaranteeTemplateType,
                                                         boolean restoreFlag,ProjectInfoDO projectInfoDO,BidCustomerDO bidCustomerDO,
                                                         boolean encryptionFlag,GuaranteeInstitutionDO guaranteeInstitutionDO,Date guaranteeTime){
        GuaranteeTemplatePdfParams pdfParams = new GuaranteeTemplatePdfParams();
        // 眉山所需字段
        pdfParams.setGuarantorName(guaranteeInstitutionDO.getGuarantorName());
        pdfParams.setGuarantorAddress(guaranteeInstitutionDO.getGuarantorAddress());
        pdfParams.setBidderCode(bidCustomerDO.getBidderCreditCode());

        pdfParams.setGuaranteeTemplateType(guaranteeTemplateType);
        pdfParams.setGuaranteeNo(applyOrderInfoDO.getGuaranteeNo());
        pdfParams.setTenderName(projectInfoDO.getTenderer());
        pdfParams.setBidderName(applyOrderInfoDO.getBidCustomerName());

        String projectName = projectInfoDO.getProjectName();
        String sectionName = projectInfoDO.getSectionName();
        if (CreateGuaranteeUtil.isGuoGu(centerNoEnum)) {
            if (StringUtils.isBlank(projectName)) {
                projectName = "";
            }

            if (StringUtils.isBlank(sectionName)) {
                sectionName = "";
            }

            if (StringUtils.isNotBlank(projectName) && StringUtils.isNotBlank(sectionName)) {
                sectionName = "（" + sectionName + "）";
            }
        }

        pdfParams.setProjectName(projectName);
        pdfParams.setSectionName(sectionName);
        pdfParams.setBidBond(CurrencyUpperUtil.fenToYuan4GuaranteeBond(applyOrderInfoDO.getBidBond(), true));
        pdfParams.setBidBondLower(CurrencyUpperUtil.fenToYuan4GuaranteeBond(applyOrderInfoDO.getBidBond(), false));

        // 眉山所需字段
        pdfParams.setGuaranteeFee(CurrencyUpperUtil.fenToYuan4GuaranteeBond(applyOrderInfoDO.getGuaranteeFee(), true));
        pdfParams.setGuaranteeFeeLower(CurrencyUpperUtil.fenToYuan4GuaranteeBond(applyOrderInfoDO.getGuaranteeFee(), false));

        String[] guaranteeTimeAy = DateUtil.formateDate(guaranteeTime, "yyyy-MM-dd").split("-");
        pdfParams.setYear(guaranteeTimeAy[0]);
        pdfParams.setMonth(guaranteeTimeAy[1]);
        pdfParams.setDay(guaranteeTimeAy[2]);
        boolean isSuiXing = CreateGuaranteeUtil.isSuiXing(centerNoEnum,vo.getClientId());
        if (CreateGuaranteeUtil.isGuoGu(centerNoEnum) || CreateGuaranteeUtil.isMeiShan(centerNoEnum)) {
            //开标日期(明文),yyyy-MM-dd HH:mm:ss
            if ((restoreFlag && !encryptionFlag) || isSuiXing || (CreateGuaranteeUtil.getProjectEncryptionFlag(centerNoEnum,projectInfoDO.getProjectEncryptionFlag()) && !encryptionFlag)) {
                if (Objects.nonNull(projectInfoDO.getBidOpenTime())) {
                    String bidOpenTime = DateUtil.formateDate(projectInfoDO.getBidOpenTime(), "yyyy-MM-dd HH:mm:ss");
                    log.info("受理订单号[{}],开标日期(明文)=[{}]", applyOrderInfoDO.getAcceptOrderNo(), bidOpenTime);
                    String[] bidOpenTimeAy = bidOpenTime.split(" ")[0].split("-");
                    pdfParams.setOpenY(bidOpenTimeAy[0]);
                    pdfParams.setOpenM(bidOpenTimeAy[1]);
                    pdfParams.setOpenD(bidOpenTimeAy[2]);
                } else {
                    pdfParams.setOpenY("******");
                    pdfParams.setOpenM("******");
                    pdfParams.setOpenD("******");
                }
            } else {
                String ciphertext = projectInfoDO.getCiphertext();
                log.info("受理订单号[{}],开标日期(密文)=[{}]", applyOrderInfoDO.getAcceptOrderNo(), ciphertext);
                if (StringUtils.isNotBlank(ciphertext)) {
                    JSONObject ciphertextObject = JSON.parseObject(ciphertext);
                    if (Objects.nonNull(ciphertextObject)) {
                        String kaibiaotime;
                        if(CreateGuaranteeUtil.isMeiShan(centerNoEnum)){
                     /*       MeiShanProjectInfoDecryptionVo meiShanProjectInfoDecryptionVo = JSON.parseObject(ciphertextObject.getString("meiShanProjectInfoDecryptionVo"), MeiShanProjectInfoDecryptionVo.class);
                            kaibiaotime = meiShanProjectInfoDecryptionVo.getBzjenddate();*/
                            kaibiaotime = null;
                        } else{
                            kaibiaotime = ciphertextObject.getString("kaibiaotime");
                        }
                        pdfParams.setOpenY(StringUtils.isBlank(kaibiaotime) ? "******" : kaibiaotime);
                        pdfParams.setOpenM(StringUtils.isBlank(kaibiaotime) ? "******" : kaibiaotime);
                        pdfParams.setOpenD(StringUtils.isBlank(kaibiaotime) ? "******" : kaibiaotime);
                    }
                } else {
                    pdfParams.setOpenY("******");
                    pdfParams.setOpenM("******");
                    pdfParams.setOpenD("******");
                }
            }
        } else {
            String[] bidOpenTimeAy = DateUtil.formateDate(projectInfoDO.getBidOpenTime(), "yyyy-MM-dd").split("-");
            pdfParams.setOpenY(bidOpenTimeAy[0]);
            pdfParams.setOpenM(bidOpenTimeAy[1]);
            pdfParams.setOpenD(bidOpenTimeAy[2]);
        }


        if (CreateGuaranteeUtil.isGuoGu(centerNoEnum) || CreateGuaranteeUtil.isMeiShan(centerNoEnum)) {
            if ((restoreFlag && !encryptionFlag) || isSuiXing || (CreateGuaranteeUtil.getProjectEncryptionFlag(centerNoEnum,projectInfoDO.getProjectEncryptionFlag()) && !encryptionFlag)) {
                if (Objects.nonNull(projectInfoDO.getBidOpenTime())) {
                    String bidOpenTime = DateUtil.formateDate(projectInfoDO.getBidOpenTime(), "yyyy-MM-dd HH:mm:ss");
                    log.info("受理订单号[{}],项目发布日期(明文)=[{}]", applyOrderInfoDO.getAcceptOrderNo(), bidOpenTime);
                    String[] noticePubDateAy = bidOpenTime.split(" ")[0].split("-");
                    pdfParams.setPubYear(noticePubDateAy[0]);
                    pdfParams.setPubMonth(noticePubDateAy[1]);
                    pdfParams.setPubDay(noticePubDateAy[2]);
                } else {
                    pdfParams.setPubYear("******");
                    pdfParams.setPubMonth("******");
                    pdfParams.setPubDay("******");
                }
            } else {
                String ciphertext = projectInfoDO.getCiphertext();
                log.info("受理订单号[{}],项目发布日期(密文)=[{}]", applyOrderInfoDO.getAcceptOrderNo(), ciphertext);
                if (StringUtils.isNotBlank(ciphertext)) {
                    JSONObject ciphertextObject = JSON.parseObject(ciphertext);
                    if (Objects.nonNull(ciphertextObject)) {
                        String kaibiaotime;
                        if(CreateGuaranteeUtil.isMeiShan(centerNoEnum)){
             /*               MeiShanProjectInfoDecryptionVo meiShanProjectInfoDecryptionVo = JSON.parseObject(ciphertextObject.getString("meiShanProjectInfoDecryptionVo"), MeiShanProjectInfoDecryptionVo.class);
                            kaibiaotime = meiShanProjectInfoDecryptionVo.getBzjenddate();*/
                            kaibiaotime = null;
                        } else{
                            kaibiaotime = ciphertextObject.getString("kaibiaotime");
                        }
                        pdfParams.setPubYear(StringUtils.isBlank(kaibiaotime) ? "******" : kaibiaotime);
                        pdfParams.setPubMonth(StringUtils.isBlank(kaibiaotime) ? "******" : kaibiaotime);
                        pdfParams.setPubDay(StringUtils.isBlank(kaibiaotime) ? "******" : kaibiaotime);
                    } else {
                        pdfParams.setPubYear("******");
                        pdfParams.setPubMonth("******");
                        pdfParams.setPubDay("******");
                    }
                } else {
                    pdfParams.setPubYear("******");
                    pdfParams.setPubMonth("******");
                    pdfParams.setPubDay("******");
                }
            }
        } else {
            if (projectInfoDO.getNoticePubDate() != null) {
                String[] noticePubDateAy = DateUtil.formateDate(projectInfoDO.getNoticePubDate(), "yyyy-MM-dd").split("-");
                pdfParams.setPubYear(noticePubDateAy[0]);
                pdfParams.setPubMonth(noticePubDateAy[1]);
                pdfParams.setPubDay(noticePubDateAy[2]);
            }
        }


        if (CreateGuaranteeUtil.isGuoGu(centerNoEnum) || CreateGuaranteeUtil.isMeiShan(centerNoEnum)) {
            if ((restoreFlag && !encryptionFlag) || isSuiXing || (CreateGuaranteeUtil.getProjectEncryptionFlag(centerNoEnum,projectInfoDO.getProjectEncryptionFlag()) && !encryptionFlag)) {
                if (Objects.nonNull(projectInfoDO.getBidOpenTime())) {
                    Date serviceLastDate = projectInfoService.getServiceEndDate(projectInfoDO);
                    if (correctGuaranteeDO != null && correctGuaranteeDO.getServiceEndTime() != null) {
                        serviceLastDate = correctGuaranteeDO.getServiceEndTime();
                    }
                    String serviceEndDateFormate = DateUtil.formateDate(serviceLastDate, "yyyy-MM-dd HH:mm:ss");
                    log.info("受理订单号[{}],保函服务终止时间(明文)=[{}]", applyOrderInfoDO.getAcceptOrderNo(), serviceEndDateFormate);
                    String[] serviceLastDateAy = serviceEndDateFormate.split(" ")[0].split("-");
                    pdfParams.setEndYear(serviceLastDateAy[0]);
                    pdfParams.setEndMonth(serviceLastDateAy[1]);
                    pdfParams.setEndDay(serviceLastDateAy[2]);
                } else {
                    pdfParams.setEndYear("******");
                    pdfParams.setEndMonth("******");
                    pdfParams.setEndDay("******");
                }
            } else {
                String ciphertext = projectInfoDO.getCiphertext();
                log.info("受理订单号[{}],保函服务终止时间(密文)=[{}]", applyOrderInfoDO.getAcceptOrderNo(), ciphertext);
                if (StringUtils.isNotBlank(ciphertext)) {
                    JSONObject ciphertextObject = JSON.parseObject(ciphertext);
                    if (Objects.nonNull(ciphertextObject)) {
                        String kaibiaotime;
                        if(CreateGuaranteeUtil.isMeiShan(centerNoEnum)){
/*                            MeiShanProjectInfoDecryptionVo meiShanProjectInfoDecryptionVo = JSON.parseObject(ciphertextObject.getString("meiShanProjectInfoDecryptionVo"), MeiShanProjectInfoDecryptionVo.class);
                            kaibiaotime = meiShanProjectInfoDecryptionVo.getBzjenddate();*/
                            kaibiaotime = null;
                        } else{
                            kaibiaotime = ciphertextObject.getString("kaibiaotime");
                        }
                        pdfParams.setEndYear(StringUtils.isBlank(kaibiaotime) ? "******" : kaibiaotime);
                        pdfParams.setEndMonth(StringUtils.isBlank(kaibiaotime) ? "******" : kaibiaotime);
                        pdfParams.setEndDay(StringUtils.isBlank(kaibiaotime) ? "******" : kaibiaotime);
                    } else {
                        pdfParams.setEndYear("******");
                        pdfParams.setEndMonth("******");
                        pdfParams.setEndDay("******");
                    }
                } else {
                    pdfParams.setEndYear("******");
                    pdfParams.setEndMonth("******");
                    pdfParams.setEndDay("******");
                }
            }
        } else {
            Date serviceEndDate = projectInfoService.getServiceEndDate(projectInfoDO);
            Date serviceLastDate = Date.from(serviceEndDate.toInstant().plus(30, ChronoUnit.DAYS));
            if (correctGuaranteeDO != null && correctGuaranteeDO.getServiceEndTime() != null) {
                serviceLastDate = correctGuaranteeDO.getServiceEndTime();
            }
            String[] serviceLastDateAy = DateUtil.formateDate(serviceLastDate, "yyyy-MM-dd").split("-");
            pdfParams.setEndYear(serviceLastDateAy[0]);
            pdfParams.setEndMonth(serviceLastDateAy[1]);
            pdfParams.setEndDay(serviceLastDateAy[2]);
        }

        pdfParams.setTenderAddress(projectInfoDO.getTendererAddress());

        //取投标人的注册地址赋值给电子保函文件中的投保人地址
        pdfParams.setBidderAddress(bidCustomerDO.getBidderRegAddress());



        if (!CreateGuaranteeUtil.isGuoGu(centerNoEnum) && !CreateGuaranteeUtil.isMeiShan(centerNoEnum)) {
            if (StringUtils.isBlank(pdfParams.getProjectName())) {
                throw new RuntimeException("参数校验异常：" + "项目名称不能为空");
            }

            if (StringUtils.isBlank(pdfParams.getSectionName())) {
                throw new RuntimeException("参数校验异常：" + "标段名称不能为空");
            }
        }
        return pdfParams;
    }

    @Transactional(rollbackFor = Exception.class)
    public InnerBaseResp receivePushGuaranteeSuccess(PushGuaranteeRespDTO resp, boolean reductionFlag) {
        log.info("受理订单号[{}],收到出函机构推送的开函成功消息.resp=[{}]", resp.getAcceptOrderNo(), JSON.toJSONString(resp));
        ApplyOrderInfoDO curApplyOrder = selectById(resp.getApplyOrderId());
        AcceptOrderInfoDO acceptOrderInfoDO = acceptOrderInfoService.getByAcceptOrderNo(resp.getAcceptOrderNo());
        CenterNoEnum centerNoEnum = exchangeCenterService.getCenterNoEnumById(acceptOrderInfoDO.getCenterId());

        //我的申请电子保函订单状态变更
        ApplyOrderInfoDO updateApplyOrderInfo = ApplyOrderInfoDO.builder().id(resp.getApplyOrderId()).guaranteeNo(resp.getGuaranteeNo()).guaranteeTime(resp.getGuaranteeTime())
                .status(ApplyOrderStatus.HAS_OUT_GUARANTEE.getStatus()).remark("出函成功").gmtModified(Date.from(Instant.now())).build();
        this.updateById(updateApplyOrderInfo);

        //我的受理电子保函订单状态变更
        AcceptOrderInfoDO updateAcceptOrderInfo = AcceptOrderInfoDO.builder().guaranteeNo(resp.getGuaranteeNo())
                .status(AcceptOrderStatus.HAS_OUT_GUARANTEE.getStatus()).remark("出函成功").gmtModified(Date.from(Instant.now())).build();
        if(CreateGuaranteeUtil.isMeiShan(centerNoEnum)){
            ProjectInfoDO projectInfoDO = projectInfoService.selectById(acceptOrderInfoDO.getProjectId());
            if(!reductionFlag && projectInfoDO.getProjectEncryptionFlag()==1){
                updateAcceptOrderInfo.setGuaranteeTime(resp.getGuaranteeTime());
            }
        }else {
            if(!reductionFlag){
                updateAcceptOrderInfo.setGuaranteeTime(resp.getGuaranteeTime());
            }
        }

        acceptOrderInfoService.updateByAcceptOrderNo(updateAcceptOrderInfo, resp.getAcceptOrderNo());

        // 电子保函以及到账凭证签章后附件 保存
        GuaranteeAttachmentInfoDO guaranteeAttachmentInfo = new GuaranteeAttachmentInfoDO();
        guaranteeAttachmentInfo.setAcceptOrderNo(curApplyOrder.getAcceptOrderNo());
        guaranteeAttachmentInfo.setCenterId(curApplyOrder.getCenterId());
        guaranteeAttachmentInfo.setOrgId(curApplyOrder.getOrgId());
        guaranteeAttachmentInfo.setType(AttachmentFileType.TYPE_7.getType());
        guaranteeAttachmentInfo.setFilePath(elgResourceService.getRelativePath(resp.getGuaranteeFile()));
        guaranteeAttachmentInfo.setFileType(elgResourceService.getFileType(resp.getGuaranteeFile()));
        guaranteeAttachmentInfo.setFileName(elgResourceService.getFileName(resp.getGuaranteeFile()));
        guaranteeAttachmentInfo.setFileMd5(elgResourceService.getFileMD5AsHex(resp.getGuaranteeFile()));

        GuaranteeAttachmentInfoDO receiveAmtAttachmentInfo = new GuaranteeAttachmentInfoDO();
        receiveAmtAttachmentInfo.setAcceptOrderNo(curApplyOrder.getAcceptOrderNo());
        receiveAmtAttachmentInfo.setCenterId(curApplyOrder.getCenterId());
        receiveAmtAttachmentInfo.setOrgId(curApplyOrder.getOrgId());
        receiveAmtAttachmentInfo.setType(AttachmentFileType.TYPE_6.getType());
        receiveAmtAttachmentInfo.setFilePath(elgResourceService.getRelativePath(resp.getReceiveAmtFile()));
        receiveAmtAttachmentInfo.setFileType(elgResourceService.getFileType(resp.getReceiveAmtFile()));
        receiveAmtAttachmentInfo.setFileName(elgResourceService.getFileName(resp.getReceiveAmtFile()));
        receiveAmtAttachmentInfo.setFileMd5(elgResourceService.getFileMD5AsHex(resp.getReceiveAmtFile()));

        GuaranteeAttachmentInfoDO allFileOfdAttachmentInfo =  new GuaranteeAttachmentInfoDO();
        boolean synthesisGuaranteeAllOfd = CreateGuaranteeUtil.isSynthesisGuaranteeAllOfd(centerNoEnum, acceptOrderInfoDO.getClientId());
        if (synthesisGuaranteeAllOfd) {
            allFileOfdAttachmentInfo.setAcceptOrderNo(curApplyOrder.getAcceptOrderNo());
            allFileOfdAttachmentInfo.setCenterId(curApplyOrder.getCenterId());
            allFileOfdAttachmentInfo.setOrgId(curApplyOrder.getOrgId());
            allFileOfdAttachmentInfo.setType(AttachmentFileType.TYPE_0.getType());
            allFileOfdAttachmentInfo.setFilePath(elgResourceService.getRelativePath(resp.getAllFileOfdPath()));
            allFileOfdAttachmentInfo.setFileType(elgResourceService.getFileType(resp.getAllFileOfdPath()));
            allFileOfdAttachmentInfo.setFileName(elgResourceService.getFileName(resp.getAllFileOfdPath()));
            allFileOfdAttachmentInfo.setFileMd5(elgResourceService.getFileMD5AsHex(resp.getAllFileOfdPath()));
        }

        GuaranteeAttachmentInfoDO applyFileAttachmentInfo = new GuaranteeAttachmentInfoDO();
        applyFileAttachmentInfo.setAcceptOrderNo(curApplyOrder.getAcceptOrderNo());
        applyFileAttachmentInfo.setCenterId(curApplyOrder.getCenterId());
        applyFileAttachmentInfo.setOrgId(curApplyOrder.getOrgId());
        applyFileAttachmentInfo.setType(AttachmentFileType.TYPE_11.getType());
        applyFileAttachmentInfo.setFilePath(elgResourceService.getRelativePath(resp.getApplyFile()));
        applyFileAttachmentInfo.setFileType(elgResourceService.getFileType(resp.getApplyFile()));
        applyFileAttachmentInfo.setFileName(elgResourceService.getFileName(resp.getApplyFile()));
        applyFileAttachmentInfo.setFileMd5(elgResourceService.getFileMD5AsHex(resp.getApplyFile()));

        GuaranteeAttachmentInfoDO qualificationInfo = new GuaranteeAttachmentInfoDO();
        qualificationInfo.setAcceptOrderNo(curApplyOrder.getAcceptOrderNo());
        qualificationInfo.setCenterId(curApplyOrder.getCenterId());
        qualificationInfo.setOrgId(curApplyOrder.getOrgId());
        qualificationInfo.setType(AttachmentFileType.TYPE_2.getType());
        qualificationInfo.setFilePath(elgResourceService.getRelativePath(resp.getQualificationPath()));
        qualificationInfo.setFileType(elgResourceService.getFileType(resp.getQualificationPath()));
        qualificationInfo.setFileName("资质证书");
        qualificationInfo.setFileMd5(elgResourceService.getFileMD5AsHex(resp.getQualificationPath()));

        GuaranteeAttachmentInfoDO licenseInfo = new GuaranteeAttachmentInfoDO();
        licenseInfo.setAcceptOrderNo(curApplyOrder.getAcceptOrderNo());
        licenseInfo.setCenterId(curApplyOrder.getCenterId());
        licenseInfo.setOrgId(curApplyOrder.getOrgId());
        licenseInfo.setType(AttachmentFileType.TYPE_3.getType());
        licenseInfo.setFilePath(elgResourceService.getRelativePath(resp.getLicensePath()));
        licenseInfo.setFileType(elgResourceService.getFileType(resp.getLicensePath()));
        licenseInfo.setFileName("营业执照");
        licenseInfo.setFileMd5(elgResourceService.getFileMD5AsHex(resp.getLicensePath()));

        GuaranteeAttachmentInfoDO ofdXmlInfo = new GuaranteeAttachmentInfoDO();
        if (synthesisGuaranteeAllOfd) {
            ofdXmlInfo.setAcceptOrderNo(curApplyOrder.getAcceptOrderNo());
            ofdXmlInfo.setCenterId(curApplyOrder.getCenterId());
            ofdXmlInfo.setOrgId(curApplyOrder.getOrgId());
            ofdXmlInfo.setType(AttachmentFileType.TYPE_14.getType());
            ofdXmlInfo.setFilePath(elgResourceService.getRelativePath(resp.getOfdStructXmlPath()));
            ofdXmlInfo.setFileType(elgResourceService.getFileType(resp.getOfdStructXmlPath()));
            ofdXmlInfo.setFileName(elgResourceService.getFileName(resp.getOfdStructXmlPath()));
            ofdXmlInfo.setFileMd5(elgResourceService.getFileMD5AsHex(resp.getOfdStructXmlPath()));
        }

        List<GuaranteeAttachmentInfoDO> attachmentInfoDOList =
                Lists.newArrayList(guaranteeAttachmentInfo, receiveAmtAttachmentInfo,
                        applyFileAttachmentInfo, qualificationInfo, licenseInfo);

        if (synthesisGuaranteeAllOfd) {
            attachmentInfoDOList.add(allFileOfdAttachmentInfo);
            attachmentInfoDOList.add(ofdXmlInfo);
        }

        guaranteeAttachmentInfoService.saveOrUpdateAttachmentInfoList(attachmentInfoDOList, curApplyOrder.getAcceptOrderNo());

        //创建保函信息
        GuaranteeDO dbGuaranteeDO = guaranteeService.getGuaranteeByAcceptOrderNo(curApplyOrder.getAcceptOrderNo());
        GuaranteeDO curGuaranteeDO = resp.getGuaranteeDO();

        if (synthesisGuaranteeAllOfd) {
            curGuaranteeDO.setGuaranteeFile(allFileOfdAttachmentInfo.getFilePath());
            curGuaranteeDO.setGuaranteeFileMd5(allFileOfdAttachmentInfo.getFileMd5());
        }

        curGuaranteeDO.setGuaranteeStatus(GuaranteeStatus.PROTECTING.getStatus());
        if (dbGuaranteeDO == null) {
            curGuaranteeDO.setId(IdGenerate.getId());
            curGuaranteeDO.setGmtCreate(Date.from(Instant.now()));
            guaranteeService.insert(curGuaranteeDO);
        } else {
            curGuaranteeDO.setId(dbGuaranteeDO.getId());
            guaranteeService.updateById(curGuaranteeDO);
        }

        GuaranteeProgressInfoDO progressInfoDO = GuaranteeProgressInfoDO.builder().status(ApplyOrderStatus.WAIT_OUT_GUARANTEE.getStatus())
                .id(IdGenerate.getId()).acceptOrderNo(curGuaranteeDO.getAcceptOrderNo()).centerOrderId(curGuaranteeDO.getCenterOrderId())
                .orderType(ApplyOrderStatus.orderType).title("开函完成")
                .auditStatus(1).auditRemark("已开函成功").operateUserName("系统自动").build();
        guaranteeProgressInfoService.saveGuaranteeProgressInfo(progressInfoDO);

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                GuaranteeInstitutionDO institutionDO = institutionService.getInstitutionByAcceptOrderNo(acceptOrderInfoDO.getAcceptOrderNo());
                BidCustomerDO bidCustomerDO = bidCustomerService.selectById(acceptOrderInfoDO.getBidCustomerId());
                //事务提交完成后，进行异步推送至中心，保证系统生成的文件信息已经入库
                GuarantorStatusNoticeReqDTO noticeReqDTO = GuarantorStatusNoticeReqDTO.builder()
                        .data_type("1")
                        .ordersn(resp.getAcceptOrderNo())
                        .policy_no(curGuaranteeDO.getGuaranteeNo())
                        .status("3")
                        .rate(new BigDecimal(acceptOrderInfoDO.getFeeRate()).multiply(new BigDecimal("10")).toString())
                        .service_amount(StringUtil.toYuan(curApplyOrder.getGuaranteeFee()))
                        .gurantee_link(elgResourceService.fmtNoAuthDownloadUrl(guaranteeAttachmentInfo.getFilePath()))
                        .gurantee_link_md5(guaranteeAttachmentInfo.getFileMd5())
                        .confirm_receipt_link(elgResourceService.fmtNoAuthDownloadUrl(receiveAmtAttachmentInfo.getFilePath()))
                        .confirm_receipt_link_md5(receiveAmtAttachmentInfo.getFileMd5())

                        .guarantee_detail_url(elgResourceService.buildElgFrontUrl("/#/autoLogin?mobile="
                                + bidCustomerDO.getBidderCreditCode() + "&ordersn=" + acceptOrderInfoDO.getAcceptOrderNo()))

                        .order_file_url(elgResourceService.fmtNoAuthDownloadUrl(applyFileAttachmentInfo.getFilePath()))
                        .order_file_md5(applyFileAttachmentInfo.getFileMd5())
                        .guarantor_name(institutionDO.getGuarantorName())
                        .guarantor_credit_code(institutionDO.getGuarantorCreditCode())
                        .guarantor_contact_name(institutionDO.getGuarantorBusinessName())
                        .guarantor_contact_phone(institutionDO.getGuarantorBusinessTel())
                        .build();
                if(CenterNoEnum.FUZHOU.equals(centerNoEnum)){
                    noticeReqDTO.setGuarantee_detail_url(elgResourceService.buildElgFrontUrl("/#/autoLogin?mobile="
                            + bidCustomerDO.getBidderCreditCode() + "&ordersn=" + acceptOrderInfoDO.getAcceptOrderNo()));
                }
                if (synthesisGuaranteeAllOfd) {
                    noticeReqDTO.setGurantee_ofd_link(elgResourceService.fmtNoAuthDownloadUrl(allFileOfdAttachmentInfo.getFilePath()));
                    noticeReqDTO.setGurantee_ofd_link_md5(allFileOfdAttachmentInfo.getFileMd5());

                    noticeReqDTO.setGuarantee_xml_url(elgResourceService.fmtNoAuthDownloadUrl(ofdXmlInfo.getFilePath()));
                    noticeReqDTO.setGuarantee_xml_md5(ofdXmlInfo.getFileMd5());
                }

                GuaranteeAttachmentInfoDO guaranteeAttachmentInfoDO =
                        guaranteeAttachmentInfoService.get(guaranteeAttachmentInfo.getCenterId(),
                                guaranteeAttachmentInfo.getOrgId(),
                                guaranteeAttachmentInfo.getAcceptOrderNo(),
                                AttachmentFileType.TYPE_8);
                if (guaranteeAttachmentInfoDO != null) {
                    noticeReqDTO.setInvoice_link(elgResourceService.fmtNoAuthDownloadUrl(guaranteeAttachmentInfoDO.getFilePath()));
                    noticeReqDTO.setInvoice_link_md5(guaranteeAttachmentInfoDO.getFileMd5());
                }
                curGuaranteeDO.setRate(acceptOrderInfoDO.getFeeRate());
                //todo:alan 龙岩中心需要先上传保函文件，再推送投保结果通知，不确定其他中心是否有影响
                if (CenterNoEnum.LONGYAN.equals(centerNoEnum)) {
                    pushGuarantee("1", curGuaranteeDO, noticeReqDTO, reductionFlag);
                } else if (CreateGuaranteeUtil.isGuoGu(centerNoEnum)) {
                    if (reductionFlag) {
                        reductionResultNotify(acceptOrderInfoDO.getClientId(), "1", curGuaranteeDO, noticeReqDTO);
                    } else {
                        pushGuarantee("1", curGuaranteeDO, noticeReqDTO, reductionFlag);
                    }
                    if(CreateGuaranteeUtil.isSuiXing(centerNoEnum,acceptOrderInfoDO.getClientId())){
                        ElgLogger.info(log, l -> l.info("receivePushGuaranteeSuccess invoiceResultNotify >> acceptOrderNo：{}", resp.getAcceptOrderNo()));
                        invoiceHelper.invoiceResultNotify(resp.getAcceptOrderNo());
                    }
                } else if (CenterNoEnum.PUTIAN.equals(centerNoEnum)) {
                    pushGuarantee("1", curGuaranteeDO, noticeReqDTO, reductionFlag);
                } else if (CreateGuaranteeUtil.isMeiShan(centerNoEnum)) {
                    pushGuarantee("1", curGuaranteeDO, noticeReqDTO, reductionFlag);
                    subAccountDelete(acceptOrderInfoDO);
                } else {
                    pushGuarantee("1", curGuaranteeDO, noticeReqDTO, reductionFlag);
                    uploadGuaranteeByGuaranteeFileType(curGuaranteeDO);
                }
            }
        });

        return InnerBaseResp.success(null);
    }

    private void subAccountDelete(AcceptOrderInfoDO acceptOrderInfoDO){
        try {
            boolean subAccountCloseFlag = CashServiceUtil.subAccountCloseFlag(acceptOrderInfoDO.getSubAccount());
            log.info("subAccountDelete acceptOrderNo:{};subAccount:{};subAccountCloseFlag:{}",acceptOrderInfoDO.getAcceptOrderNo(),acceptOrderInfoDO.getSubAccount(),subAccountCloseFlag);
            if (!subAccountCloseFlag) {
                // 关闭子账户
                boolean subAccountDeleteFlag = CashServiceUtil.subAccountDeleteFlag(acceptOrderInfoDO.getSubAccount());
                log.info("subAccountDelete acceptOrderNo:{};subAccount:{};subAccountDeleteFlag:{}",acceptOrderInfoDO.getAcceptOrderNo(),acceptOrderInfoDO.getSubAccount(),subAccountDeleteFlag);
            }
        }catch (Exception e) {
            log.error("subAccountDelete error.acceptOrderNo:{};subAccount:{};",acceptOrderInfoDO.getAcceptOrderNo(),acceptOrderInfoDO.getSubAccount());
        }
    }

    /**
     * 同步上传保函文件
     *
     * @param curGuaranteeDO
     */
    private void uploadGuaranteeByGuaranteeFile(GuaranteeDO curGuaranteeDO) {
        InnerUploadBaohanFileBo bo = new InnerUploadBaohanFileBo();
        bo.setAcceptOrderNo(curGuaranteeDO.getAcceptOrderNo());
        bo.setApplyno(curGuaranteeDO.getCenterOrderId());
        bo.setBaohanno(curGuaranteeDO.getGuaranteeNo());
        try {
            CenterNoEnum centerNoEnum = exchangeCenterService.getCenterNoEnumByAcceptOrderNo(curGuaranteeDO.getAcceptOrderNo());
            CenterInterfaceService cService = CenterInterfaceServiceFactory.getByCenterNoEnum(centerNoEnum);

            //审核通过上送密函及保函信息才有落库||下载密钥&上传保函及保函上传完成通知成功
            InnerBaseResp innerBaseResp = cService.uploadBaohanFile(curGuaranteeDO.getAcceptOrderNo(), bo);
            if (innerBaseResp != null && innerBaseResp.getRespCode().isSuccess()) {
                ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步上传文件成功：响应报文：{}", curGuaranteeDO.getAcceptOrderNo(), JSON.toJSONString(innerBaseResp)));
            } else {
                noticeRetryInfoService.saveOrUpdateNoticeRetryInfo(NoticeTypeEnum.upload_guarantee_file,
                        curGuaranteeDO.getCenterId(), curGuaranteeDO.getOrgId(),
                        curGuaranteeDO.getAcceptOrderNo(), bo, null, innerBaseResp
                );
                ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步上传文件失败,待下次上传：响应报文：{}", curGuaranteeDO.getAcceptOrderNo(), JSON.toJSONString(innerBaseResp)));
            }

        } catch (Exception e) {
            InnerBaseResp innerBaseResp = InnerBaseResp.exception(e.getMessage());
            ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步上传文件异常,待下次上传：{}", curGuaranteeDO.getAcceptOrderNo(), e.getMessage(), e));
            noticeRetryInfoService.saveOrUpdateNoticeRetryInfo(NoticeTypeEnum.upload_guarantee_file,
                    curGuaranteeDO.getCenterId(), curGuaranteeDO.getOrgId(),
                    curGuaranteeDO.getAcceptOrderNo(), bo, null, innerBaseResp
            );
        }
    }

    /**
     * 异步上传保函文件
     *
     * @param curGuaranteeDO
     */
    private void uploadGuaranteeByGuaranteeFileType(GuaranteeDO curGuaranteeDO) {
        CompletableFuture.runAsync(() -> {
            InnerUploadBaohanFileBo bo = new InnerUploadBaohanFileBo();
            bo.setAcceptOrderNo(curGuaranteeDO.getAcceptOrderNo());
            bo.setApplyno(curGuaranteeDO.getCenterOrderId());
            bo.setBaohanno(curGuaranteeDO.getGuaranteeNo());
            try {
                CenterNoEnum centerNoEnum = exchangeCenterService.getCenterNoEnumByAcceptOrderNo(curGuaranteeDO.getAcceptOrderNo());
                CenterInterfaceService cService = CenterInterfaceServiceFactory.getByCenterNoEnum(centerNoEnum);

                //审核通过上送密函及保函信息才有落库||下载密钥&上传保函及保函上传完成通知成功
                InnerBaseResp innerBaseResp = cService.uploadBaohanFile(curGuaranteeDO.getAcceptOrderNo(), bo);
                if (innerBaseResp != null && innerBaseResp.getRespCode().isSuccess()) {
                    ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步上传文件成功：响应报文：{}", curGuaranteeDO.getAcceptOrderNo(), JSON.toJSONString(innerBaseResp)));
                } else {
                    noticeRetryInfoService.saveOrUpdateNoticeRetryInfo(NoticeTypeEnum.upload_guarantee_file,
                            curGuaranteeDO.getCenterId(), curGuaranteeDO.getOrgId(),
                            curGuaranteeDO.getAcceptOrderNo(), bo, null, innerBaseResp
                    );
                    ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步上传文件失败,待下次上传：响应报文：{}", curGuaranteeDO.getAcceptOrderNo(), JSON.toJSONString(innerBaseResp)));
                }

            } catch (Exception e) {
                InnerBaseResp innerBaseResp = InnerBaseResp.exception(e.getMessage());
                ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步上传文件异常,待下次上传：{}", curGuaranteeDO.getAcceptOrderNo(), e.getMessage(), e));
                noticeRetryInfoService.saveOrUpdateNoticeRetryInfo(NoticeTypeEnum.upload_guarantee_file,
                        curGuaranteeDO.getCenterId(), curGuaranteeDO.getOrgId(),
                        curGuaranteeDO.getAcceptOrderNo(), bo, null, innerBaseResp
                );
            }
        }).whenCompleteAsync((r, e) -> {
            if (e != null) {
                ElgLogger.error(log, l -> l.error("异步上传文件异常:{}", e.getMessage(), e));
            }
        });
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public InvoiceInfoDO invoice(AcceptOrderInfoDO vo, boolean hasInvoiceNo, String invoiceLine) {
        AcceptOrderInfoDO acceptOrderInfoDO = acceptOrderInfoService.getByAcceptOrderNo(vo.getAcceptOrderNo());
        BidCustomerDO bidCustomerDO = bidCustomerService.selectById(acceptOrderInfoDO.getBidCustomerId());
        SellerInfoDO sellerInfoDO = sellerInfoService.selectOne(SellerInfoDOCondition.builder().andOrgIdEq(acceptOrderInfoDO.getOrgId()).build());
        ProjectInfoDO projectInfo = projectInfoService.selectById(vo.getProjectId());
        InvoiceInfoDO invoiceInfoDO = invoiceInfoService.selectById(acceptOrderInfoDO.getInvoiceId());
        if (invoiceInfoDO == null) {
            invoiceInfoDO = new InvoiceInfoDO();
            invoiceInfoDO.setId(IdGenerate.getId());
        }
        invoiceInfoDO.setAcceptOrderNos(vo.getAcceptOrderNo());
        invoiceInfoDO.setCenterId(acceptOrderInfoDO.getCenterId());
        invoiceInfoDO.setOrgId(acceptOrderInfoDO.getOrgId());
        invoiceInfoDO.setInvoiceTitle(bidCustomerDO.getBidderName());
        //开票类型蓝票
        invoiceInfoDO.setInvoiceType(1);
//        invoiceInfoDO.setInvoiceNo();
        invoiceInfoDO.setCustomerName(bidCustomerDO.getBidderName());
        invoiceInfoDO.setCustomerCreditCode(bidCustomerDO.getBidderCreditCode());
        invoiceInfoDO.setCustomerBankCode(bidCustomerDO.getLicenseAccount());
        invoiceInfoDO.setCustomerOpneBank(bidCustomerDO.getLicenseBank());
        invoiceInfoDO.setCustomerAddress(bidCustomerDO.getBidderRegAddress());
//        invoiceInfoDO.setCustomerPhone(bidCustomerDO.getBidderContactTel());
        //发票购买方电话若有开票座机号则取该值，其他默认取客户经办人联系电话
        String customerPhone = StringUtils.isNotBlank(bidCustomerDO.getComTelNum()) ? bidCustomerDO.getComTelNum() : bidCustomerDO.getBidderContactTel();
        invoiceInfoDO.setCustomerPhone(customerPhone);

        invoiceInfoDO.setCustomerContactName(bidCustomerDO.getBidderContactName());
        invoiceInfoDO.setCustomerContactTel(bidCustomerDO.getBidderContactTel());

        //todo:alan 客户邮箱错误 会导致开票失败  需要增加邮箱格式校验
        invoiceInfoDO.setCustomerContactEamil(bidCustomerDO.getBidderEamil());
        invoiceInfoDO.setCustomerContactAddress(bidCustomerDO.getBidderRegAddress());
        invoiceInfoDO.setAmount(acceptOrderInfoDO.getGuaranteeFee());
        invoiceInfoDO.setAmountOfChinaese(CurrencyUpperUtil.fenToCurrencyUpper(acceptOrderInfoDO.getGuaranteeFee()));
        invoiceInfoDO.setSellerName(sellerInfoDO.getSellerName());
        invoiceInfoDO.setSellerCreditCode(sellerInfoDO.getSellerCreditCode());
        invoiceInfoDO.setSellerBankCode(sellerInfoDO.getSellerBankCode());
        invoiceInfoDO.setSellerOpenBank(sellerInfoDO.getSellerOpenBank());
        invoiceInfoDO.setSellerAddress(sellerInfoDO.getSellerAddress());
        invoiceInfoDO.setSellerPhone(sellerInfoDO.getSellerPhone());
        invoiceInfoDO.setHandler(sellerInfoDO.getHandler());
        invoiceInfoDO.setInvoiceRemark("电子保函");
        invoiceInfoDO.setOrderCount(1);
        invoiceInfoDO.setGmtCreate(new Date());
        if (StringUtils.isNotBlank(invoiceLine)) {
            invoiceInfoDO.setInvoiceLine(invoiceLine);
        }

        AcceptOrderInfoDO updateAcceptOrder = AcceptOrderInfoDO.builder().id(vo.getId())
                .invoiceId(invoiceInfoDO.getId()).build();

        vo.setInvoiceId(invoiceInfoDO.getId());

        if (hasInvoiceNo) {
            invoiceInfoDO.setStatus(InvoiceStatusEnum.INVOICED.getValue());
            invoiceInfoDO.setInvoiceNo(vo.getInvoiceNo());
            invoiceInfoDO.setInvoiceMode(0);

            //已开票
            vo.setInvoiceFlag(InvoiceFlagEnum.INVOICED.getValue());
            updateAcceptOrder.setInvoiceFlag(InvoiceFlagEnum.INVOICED.getValue());
        } else {
            String invoiceSerialNum = invoiceHelper.requestBillingNew(vo.getAcceptOrderNo(), invoiceInfoDO, projectInfo.getProjectName());
            invoiceInfoDO.setStatus(InvoiceStatusEnum.PROSESS.getValue());
            invoiceInfoDO.setSerialNo(invoiceSerialNum);
            invoiceInfoDO.setInvoiceMode(1);
            //申请开票中，待查询开票结果
            vo.setInvoiceFlag(InvoiceFlagEnum.INVOICEAPPLY.getValue());
            updateAcceptOrder.setInvoiceFlag(InvoiceFlagEnum.INVOICEAPPLY.getValue());
        }
        invoiceInfoService.save(invoiceInfoDO, updateAcceptOrder);
        return invoiceInfoDO;
    }

    /**
     * @param applyStatus    是	是否审核通过  1：审核通过  0：审核未通过
     * @param curGuaranteeDO 保函信息表
     */
    public void pushGuarantee(String applyStatus, GuaranteeDO curGuaranteeDO, GuarantorStatusNoticeReqDTO noticeReqDTO, boolean reductionFlag) {
        CompletableFuture.runAsync(() -> {
            CenterNoEnum centerNoEnum = exchangeCenterService.getCenterNoEnumByAcceptOrderNo(curGuaranteeDO.getAcceptOrderNo());
            //todo:alan 龙岩中心需要先上传保函文件，再推送投保结果通知，不确定其他中心是否有影响
            if (CenterNoEnum.LONGYAN.equals(centerNoEnum) || CreateGuaranteeUtil.isMeiShan(centerNoEnum)) {
                uploadGuaranteeByGuaranteeFile(curGuaranteeDO);
            }
            PushCenterGuaranteeBo bo = new PushCenterGuaranteeBo();
            bo.setGuaranteeVo(curGuaranteeDO.buildVo());
            bo.setApplyStatus(applyStatus);
            bo.setGuarantorStatusNoticeReqDTO(noticeReqDTO);
            try {
                CenterInterfaceService cService = CenterInterfaceServiceFactory.getByCenterNoEnum(centerNoEnum);

                InnerBaseResp innerBaseResp = cService.pushGuarantee(bo);
                //审核通过保函信息才有落库
                if ("1".equals(applyStatus)) {
                    GuaranteeDO update = GuaranteeDO.builder().id(curGuaranteeDO.getId()).build();
                    update.setGmtModified(new Date());
                    update.setPushRespMsg(innerBaseResp.getMessage());
                    if (innerBaseResp.getRespCode() == InnerRespCode.SUCCESS) {
                        update.setPushFlag(1);
                        if (CenterNoEnum.FUZHOU.equals(centerNoEnum)) {
                            PushCenterGuaranteeBo pushCenterGuaranteeBo = (PushCenterGuaranteeBo) innerBaseResp.getData();
                            update.setSerialNum(pushCenterGuaranteeBo.getGuaranteeVo().getSerialNum());
                        }
                    } else {
                        update.setPushFlag(2);
                    }
                    guaranteeService.updateById(update);
                }
                if (innerBaseResp != null && innerBaseResp.getRespCode().isSuccess()) {
                    ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步推送申请保函结果成功：响应报文：{}", curGuaranteeDO.getAcceptOrderNo(), JSON.toJSONString(innerBaseResp)));
                } else {
                    noticeRetryInfoService.saveOrUpdateNoticeRetryInfo(NoticeTypeEnum.guarantee_apply_result,
                            curGuaranteeDO.getCenterId(), curGuaranteeDO.getOrgId(),
                            curGuaranteeDO.getAcceptOrderNo(), bo, null, innerBaseResp
                    );
                    ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步推送申请保函结果失败,待下次通知：响应报文：{}", curGuaranteeDO.getAcceptOrderNo(), JSON.toJSONString(innerBaseResp)));
                }
            } catch (Exception e) {
                InnerBaseResp innerBaseResp = InnerBaseResp.exception(e.getMessage());
                ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步推送申请保函异常：{}", curGuaranteeDO.getAcceptOrderNo(), e.getMessage(), e));
                noticeRetryInfoService.saveOrUpdateNoticeRetryInfo(NoticeTypeEnum.guarantee_apply_result,
                        curGuaranteeDO.getCenterId(), curGuaranteeDO.getOrgId(),
                        curGuaranteeDO.getAcceptOrderNo(), bo, null, innerBaseResp
                );
            }
        });
    }

    /**
     * 还原结果推送
     *
     * @param applyStatus    是	是否审核通过  1：审核通过  0：审核未通过
     * @param curGuaranteeDO 保函信息表
     */
    public void reductionResultNotify(String clientId, String applyStatus, GuaranteeDO curGuaranteeDO, GuarantorStatusNoticeReqDTO noticeReqDTO) {
        CompletableFuture.runAsync(() -> {
            CenterNoEnum centerNoEnum = exchangeCenterService.getCenterNoEnumByAcceptOrderNo(curGuaranteeDO.getAcceptOrderNo());
            PushCenterGuaranteeBo bo = new PushCenterGuaranteeBo();
            bo.setGuaranteeVo(curGuaranteeDO.buildVo());
            bo.setApplyStatus(applyStatus);
            bo.setGuarantorStatusNoticeReqDTO(noticeReqDTO);
            try {
                CenterInterfaceService cService = CenterInterfaceServiceFactory.getByCenterNoEnum(centerNoEnum);

                // 还原结果推送
                GuoGuReductionNotifyReq guoGuInvoiceNotifyReq = new GuoGuReductionNotifyReq();
                GuaranteeVo guaranteeVo = bo.getGuaranteeVo();
                guoGuInvoiceNotifyReq.setTradeNo(guaranteeVo.getCenterOrderId());
                guoGuInvoiceNotifyReq.setInsureOrderNo(guaranteeVo.getGuaranteeNo());
                guoGuInvoiceNotifyReq.setDownloadUrl(bo.getGuarantorStatusNoticeReqDTO().getGurantee_link());
                guoGuInvoiceNotifyReq.setReleaseTime(DateUtil.formateDate(curGuaranteeDO.getServiceBeginTime(), DateUtil.FORMAT_DATETIME));
                InnerBaseResp innerBaseResp = cService.reductionResultNotify(clientId, guoGuInvoiceNotifyReq, centerNoEnum);
                //审核通过保函信息才有落库
                if ("1".equals(applyStatus)) {
                    GuaranteeDO update = GuaranteeDO.builder().id(curGuaranteeDO.getId()).build();
                    update.setGmtModified(new Date());
                    update.setPushRespMsg(innerBaseResp.getMessage());
                    if (innerBaseResp.getRespCode() == InnerRespCode.SUCCESS) {
                        update.setPushFlag(1);
                    } else {
                        update.setPushFlag(2);
                    }
                    guaranteeService.updateById(update);
                }
                if (innerBaseResp != null && innerBaseResp.getRespCode().isSuccess()) {
                    ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步 还原结果推送成功：响应报文：{}", curGuaranteeDO.getAcceptOrderNo(), JSON.toJSONString(innerBaseResp)));
                } else {
                    noticeRetryInfoService.saveOrUpdateNoticeRetryInfo(NoticeTypeEnum.guarantee_apply_result,
                            curGuaranteeDO.getCenterId(), curGuaranteeDO.getOrgId(),
                            curGuaranteeDO.getAcceptOrderNo(), bo, null, innerBaseResp
                    );
                    ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步 还原结果推送失败,待下次通知：响应报文：{}", curGuaranteeDO.getAcceptOrderNo(), JSON.toJSONString(innerBaseResp)));
                }
            } catch (Exception e) {
                InnerBaseResp innerBaseResp = InnerBaseResp.exception(e.getMessage());
                ElgLogger.info(log, log -> log.info("受理订单号[{}] >> 异步 还原结果推送异常：{}", curGuaranteeDO.getAcceptOrderNo(), e.getMessage(), e));
                noticeRetryInfoService.saveOrUpdateNoticeRetryInfo(NoticeTypeEnum.guarantee_apply_result,
                        curGuaranteeDO.getCenterId(), curGuaranteeDO.getOrgId(),
                        curGuaranteeDO.getAcceptOrderNo(), bo, null, innerBaseResp
                );
            }
        },executor);
    }


    public ApplyOrderDetailVO getApplyOrderDetailById(Long id) {
        Assert.notNull(id, () -> "Id不能为空");
        Map<String, Object> params = Maps.newHashMap();
        params.put("id", id);
        ApplyOrderDetailVO applyOrderDetailVO = this.selectOneBySql("getApplyOrderDetailById", params);

        List<GuaranteeAttachmentInfoDO> aList = guaranteeAttachmentInfoService.getAllAttachmentByAcceptOrderNo(applyOrderDetailVO.getAcceptOrderNo());
        if (!CollectionUtils.isEmpty(aList)) {
            aList.forEach(l -> {
                if (AttachmentFileType.TYPE_0.getType() == l.getType()) {
                    applyOrderDetailVO.setAllOFDFile(l);
                } else if (AttachmentFileType.TYPE_1.getType() == l.getType()) {
                    applyOrderDetailVO.setOrigApplyFile(l);
                } else if (AttachmentFileType.TYPE_2.getType() == l.getType()) {
                    applyOrderDetailVO.setOrgQualificationFile(l);
                } else if (AttachmentFileType.TYPE_3.getType() == l.getType()) {
                    applyOrderDetailVO.setOrgBusinessLicFile(l);
                } else if (AttachmentFileType.TYPE_4.getType() == l.getType()) {
                    applyOrderDetailVO.setOpenAccountFile(l);
                } else if (AttachmentFileType.TYPE_5.getType() == l.getType()) {
                    applyOrderDetailVO.setPayProveFile(l);
                } else if (AttachmentFileType.TYPE_6.getType() == l.getType()) {
                    applyOrderDetailVO.setReceiveProveFile(l);
                } else if (AttachmentFileType.TYPE_7.getType() == l.getType()) {
                    applyOrderDetailVO.setGuaranteeFile(l);
                } else if (AttachmentFileType.TYPE_8.getType() == l.getType()) {
                    applyOrderDetailVO.setInvoiceFile(l);
                } else if (AttachmentFileType.TYPE_9.getType() == l.getType()) {
                    applyOrderDetailVO.setOtherFile(l);
                }
            });
        }
        return applyOrderDetailVO;
    }

    /**
     * 待提交资料状态：提交资料
     *
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean submitApplyData(ApplyOrderStatusOperateVO vo) {

        Path path = elgResourceService.getAbsolutePath(vo.getReceiveAmtPic());
        if (Files.notExists(path) || path.toFile().length() == 0) {
            throw new SystemRuntimeException(ErrorCode.NOTEXISTS, "到账证明附件");
        }
        String fileType = elgResourceService.getFileType(path);
        String fileName = elgResourceService.getFileName(path);
        String fileMd5 = elgResourceService.getFileMD5AsHex(path);
        ApplyOrderInfoDO applyOrderInfoDO = this.selectById(vo.getId());
        GuaranteeAttachmentInfoDO receivePic = GuaranteeAttachmentInfoDO.builder()
                .centerId(applyOrderInfoDO.getCenterId()).orgId(applyOrderInfoDO.getOrgId())
                .type(AttachmentFileType.TYPE_6.getType()).acceptOrderNo(applyOrderInfoDO.getAcceptOrderNo())
                .fileType(fileType).fileName(fileName).fileMd5(fileMd5).filePath(vo.getReceiveAmtPic()).remark("到账证明后管上传")
                .build();
        guaranteeAttachmentInfoService.saveOrUpdateAttachmentInfo(receivePic);

        ApplyOrderInfoDO updateApply = ApplyOrderInfoDO.builder().id(applyOrderInfoDO.getId()).status(ApplyOrderStatus.WAIT_APPROVAL_DATA.getStatus())
                .gmtModified(Date.from(Instant.now())).remark("到账证明附件已上传待审核").build();
        this.updateById(updateApply);

        //进度信息
        GuaranteeProgressInfoDO progressInfoDO = GuaranteeProgressInfoDO.builder().status(vo.getStatus())
                .id(IdGenerate.getId()).acceptOrderNo(applyOrderInfoDO.getAcceptOrderNo()).centerOrderId(applyOrderInfoDO.getCenterOrderId())
                .orderType(ApplyOrderStatus.orderType).title("提交资料")
                .auditStatus(1).auditRemark("到账证明").operateUserName(UserContextUtil.getCurUserName() != null ? UserContextUtil.getCurUserName() : "system").build();
        guaranteeProgressInfoService.saveGuaranteeProgressInfo(progressInfoDO);

        return true;
    }

    /**
     * 待审核状态：资料审核通过后进行签章操作
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean confirmApplyData(ApplyOrderStatusOperateVO vo) {
        ApplyOrderInfoDO applyOrderInfoDO = this.selectById(vo.getId());

        if (StringUtils.isAnyEmpty(String.valueOf(vo.getAuditStatus()), vo.getAuditRemark())) {
            throw new SystemRuntimeException(ErrorCode.ERROR, "审核状态或审核说明不能为空");
        }
        //进度信息
        GuaranteeProgressInfoDO progressInfoDO = GuaranteeProgressInfoDO.builder().status(vo.getStatus())
                .id(IdGenerate.getId()).acceptOrderNo(applyOrderInfoDO.getAcceptOrderNo()).centerOrderId(applyOrderInfoDO.getCenterOrderId())
                .orderType(ApplyOrderStatus.orderType).title("审核")
                .auditStatus(vo.getAuditStatus()).auditRemark(vo.getAuditRemark()).operateUserName(UserContextUtil.getCurUserName() != null ? UserContextUtil.getCurUserName() : "system").build();
        guaranteeProgressInfoService.saveGuaranteeProgressInfo(progressInfoDO);

        if (vo.getAuditStatus() == 1) {
            ApplyOrderInfoDO updateApply = ApplyOrderInfoDO.builder().id(applyOrderInfoDO.getId()).status(ApplyOrderStatus.WAIT_OUT_GUARANTEE.getStatus())
                    .gmtModified(Date.from(Instant.now())).remark("发起出函机构开函").build();
            this.updateById(updateApply);

            //同时进行签章操作
//            createGuaranteeContract(applyOrderInfoDO);
        } else {
            //回退到 待提交资料
            ApplyOrderInfoDO updateApply = ApplyOrderInfoDO.builder().id(applyOrderInfoDO.getId()).status(ApplyOrderStatus.WAIT_SUBMIT_DATA.getStatus())
                    .gmtModified(Date.from(Instant.now())).remark("资料审核不通过回退到待提交资料").build();
            this.updateById(updateApply);

        }

        return true;
    }

    /**
     * 待出函状态：可进行重新提交开函申请
     */
    public Boolean reApplyGuarantee(ApplyOrderStatusOperateVO vo) {
        ApplyOrderInfoDO curDo = this.selectById(vo.getId());
        //重新开函
//        this.createGuaranteeContract(curDo);

        //进度信息
        GuaranteeProgressInfoDO progressInfoDO = GuaranteeProgressInfoDO.builder().status(ApplyOrderStatus.WAIT_OUT_GUARANTEE.getStatus())
                .id(IdGenerate.getId()).acceptOrderNo(curDo.getAcceptOrderNo()).centerOrderId(curDo.getCenterOrderId())
                .orderType(ApplyOrderStatus.orderType).title("重新开函")
                .auditStatus(1).auditRemark("后管重新发起开函").operateUserName(UserContextUtil.getCurUserName() != null ? UserContextUtil.getCurUserName() : "system").build();
        guaranteeProgressInfoService.saveGuaranteeProgressInfo(progressInfoDO);


        return true;
    }


    /**
     * 支付结果推送
     *
     * @param curDO
     * @return
     */
    public boolean pushPayResult(AcceptOrderInfoDO curDO, Boolean payResultSuccess) {
        String acceptOrderNo = curDO.getAcceptOrderNo();
        CenterNoEnum centerNoEnum = exchangeCenterService.getCenterNoEnumByAcceptOrderNo(acceptOrderNo);
        if (payResultSuccess) {
            if (CreateGuaranteeUtil.isIssueInvoice(centerNoEnum,curDO.getClientId())) {
                if (curDO.getInvoiceFlag() == null || curDO.getInvoiceFlag().intValue() != 1) {
                    throw new RuntimeException("请先确认已开票");
                }
            }
        }

        if (curDO.getPushPayResultFlag() != null && curDO.getPushPayResultFlag() == 1) {
            ElgLogger.info(log, log -> log.info("受理订单号[{}] << 已同步推送支付结果成功过：无需再推送", acceptOrderNo));
            return true;
        }

        NoticePayResultBo bo = new NoticePayResultBo();
        bo.setAcceptOrderNo(acceptOrderNo);
        bo.setPayResult(payResultSuccess ? "1" : "2");
        bo.setPayResultMsg(payResultSuccess ? "支付成功" : "支付失败:" + curDO.getRemark());
        // 国谷支付通知需要该参数
        bo.setClientId(curDO.getClientId());
        try {
            CenterInterfaceService cService = CenterInterfaceServiceFactory.getByCenterNoEnum(centerNoEnum);

            InnerBaseResp innerBaseResp = cService.noticePayResult(bo);

            if (innerBaseResp != null && innerBaseResp.getRespCode().isSuccess()) {
                ElgLogger.info(log, log -> log.info("受理订单号[{}] << 同步推送支付结果成功：响应报文：{}", acceptOrderNo, JSON.toJSONString(innerBaseResp)));
                return true;
            } else {
                ElgLogger.error(log, log -> log.error("受理订单号[{}] << 同步推送支付结果失败,待人工下次通知：响应报文：{}", acceptOrderNo, JSON.toJSONString(innerBaseResp)));
                throw new RuntimeException("推送支付结果失败:" + innerBaseResp.getMessage());
            }
        } catch (Exception e) {
            ElgLogger.error(log, log -> log.error("受理订单号[{}] << 同步推送支付结果异常：{}", acceptOrderNo, e.getMessage(), e));
            throw new RuntimeException("推送支付结果异常:" + e.getMessage());
        }
    }
}
